#include <tws_config.h>
#include <QTimer>
#include <qudpsocket.h>
#include <xinifile.h>
#include <xinfomatremoteproxy.h>
#include <xqtsymbollabel.h>
#include <xwritelogexport.h>
#include "sm700.h"
#include "infomatcommon.h"          // define layouts
#include "infomatconfigdefine.h"    // configuration protocol header
#include "xinfomatconfigmanager.h"	// configuration protocol 
#include "xqueuewidget.h"           // componment: xqueuewidget (handle full screen and half screen)
#include "xinfomatlayoutmanager.h"  // control XHtmlPlayer + XMoviePlayer
#include "xlayout1.h" 			
#include "xplayerwidgetmanager.h"   // Html/Movie Player Manager

unsigned short cmdMode = 0x0;     

MainWidget::MainWidget (QWidget* parent, Qt::WFlags fl) : QWidget(parent, Qt::FramelessWindowHint), 
	m_xqueueWidget(NULL), m_xlayoutManager(NULL), m_xlayout1(NULL),
	m_socket(NULL),m_senderPort(0), m_pluNo(0), m_lblPowerOff(NULL),
	m_hasSentQueue(false),m_screenState(EPartialScreen)  
{   /* {{{ */
	m_layout = m_xbootconf.getLayout();
	this->setCursor(QCursor(Qt::BlankCursor));
	m_socket = new QUdpSocket(this);
	m_socket->bind(QHostAddress(QString(m_xudpdConf.getIp().c_str())),m_xudpdConf.getPort());
	connect(m_socket, SIGNAL(readyRead()), this, SLOT(onReadSocket()));
	connect(&m_tmCmdCtrl, SIGNAL(timeout()), this, SLOT(onFromExitScreenSaver()));
	
	/* COPY ORIGINAL FOR COMMAND SOCKET >> */
	cmdProc = new QProcess(this);
	udpSocketOut = new QUdpSocket(this);
	udpPort = 5042;
	/* Copy Done <<  ***********************/
	
	XPlayerWidgetManager* xPlayerManager = new XPlayerWidgetManager(m_layout);
	
#if 0
	createWidgets();   //not start players yet
	/*----- Start Players here ------*/
	if (NULL!= m_xlayoutManager) {
		if (0!=m_xlayoutManager->doRoutine()) {
			LOG_E("[Error] Routine Play");
		};
	} else if (NULL!=m_xlayout1) {
		if (0!=m_xlayout1->doRoutine(EPartialScreen)) {
			LOG_E("[Error] Routine Play Failed");
		}
	}

	if (EScreenModeOn == m_xbootconf.screenMode())  {
		if (NULL!=m_xlayout1) {
			connect (m_xlayout1, SIGNAL(sgWMRepaint()), this, SLOT(onWMRepaint()));  //avoid crashed screen
		} else {
			if (NULL!=m_xlayoutManager) {
				if (m_layout == k_layout_6) 
					connect(m_xlayoutManager, SIGNAL(sgQueueWidgetRepaint()), this, SLOT(onQueueWidgetRepaint())); //repaint Queue

				if (m_layout == k_layout_8 || m_layout == k_layout_9 || m_layout == k_layout_10)  {
					connect (m_xlayoutManager, SIGNAL(sgWMRepaint()), this, SLOT(onWMRepaint()));  //avoid crashed screen
				}
			}
		}
	}//EScreenModeOn
#endif
} /* }}} */

void MainWidget::createWidgets()   /* {{{ */
{ 
	switch (m_layout)
	{
	case k_layout_1:    // WM_1 + HTML + VIDEO
		m_xlayout1 = new XLayout1();
		setupUi(this);
		this->show();
		break;
	case k_layout_2:  case k_layout_4:    // WM_1 + HTML/VIDEO 
		m_xlayoutManager = new	XInfomatLayoutManager();
		assert (NULL!=m_xlayoutManager);
		setupUi(this);
		this->show(); 
		break;
	case k_layout_3:  case k_layout_5: 	// HTML/Video   Only  
		this->hide();
		m_xlayoutManager = new XInfomatLayoutManager();
		assert (NULL!= m_xlayoutManager);
		break;
	case k_layout_6:    //Queue + Video/HTML 
		m_xlayoutManager = new XInfomatLayoutManager();
		m_xqueueWidget = new XQueueWidget();
		assert (NULL!=m_xlayoutManager);
		assert (NULL!=m_xqueueWidget);
		connect(m_xqueueWidget, SIGNAL(sgShowQueueDone()), m_xlayoutManager, SLOT(onQueueDown()));
		break;
	case k_layout_7:    //Queue  
		m_xqueueWidget = new XQueueWidget();
		assert (NULL!=m_xqueueWidget);
		break;
	case k_layout_8: case k_layout_9:   //WM2 + Queue + VIDEO/HTML
		m_xlayoutManager = new	XInfomatLayoutManager();
		assert (NULL!=m_xlayoutManager);
		m_xqueueWidget = new XQueueWidget();
		assert (NULL!=m_xqueueWidget);
		connect(m_xqueueWidget, SIGNAL(sgShowQueueDone()), m_xlayoutManager, SLOT(onQueueDown()));
		setupUi(this);
		this->show();
		break;
	case k_layout_10: 	// WM_2 + QueueBody 
		setupUi(this);
		this->show();
		m_xqueueWidget = new XQueueWidget();
		break;
	default:
		m_xlayoutManager = new	XInfomatLayoutManager();
		assert (NULL!=m_xlayoutManager);
		setupUi(this);
		this->show();
		LOG_E("[Error] Layout is invalid, create a default: WeighMeasure + Video/Html");
		break;
	}
} /* }}} */

void MainWidget::onReadSocket()  /* {{{ */
{
	while (m_socket->hasPendingDatagrams()) 
	{
		QByteArray datagram;
		datagram.resize(m_socket->pendingDatagramSize());
		QHostAddress sender;
		m_socket->readDatagram(datagram.data(), datagram.size(), &sender,&m_senderPort);
		m_senderIp = sender.toString();	
		filterProtocol(datagram);
	}
}/* }}} */

void MainWidget::filterProtocol(QByteArray& datagram)  /* {{{ */
{ 
	if ( INFOMAT_CONFIG_PROTOCOL == *datagram.data()) {
		m_xconfigProtocolMgr.getInDatagram(datagram, m_senderIp);
		return ;
	}

	// process (1)W&M (2)function command (symbox text) (3)plu (4)command (5)Plu socket
	char *udpData = datagram.data();
	switch (*udpData)
	{
	case k_protocol_weight_measure: { // (1) Weight Measure
			switch (m_layout) {
			case k_layout_1:  case k_layout_2:  
			case k_layout_4:  case k_layout_8:
			case k_layout_9:  case k_layout_10: 
				processWeightMeasureSocket(datagram);
				return;
			default:
				return;
			}
		}
	case k_protocol_function_command: { // (2) Function Command : Symbox Text 
			this->processFunctionCommandSocket(datagram);
			return;
		}
	case k_protocol_f9: {
		switch (*(udpData+1)) {
		case k_protocol_f9_plu:
			processPluSocket(datagram); //  (3) plu 
			return;
		case k_protocol_f9_command:     //  (4) Command
			processCommandSocket(datagram);
			return;
		case k_protocol_f9_queue: {     //  (5) Queue
			switch (m_layout) {
			case k_layout_6: case k_layout_7: case k_layout_8: 
			case k_layout_9: case k_layout_10:
				processQueueSocket(datagram);	
				return;
			default:
				return;
			}			 
		}
		default:
			LOG_E("No such F9 protocol");
		} // f9_queue
	} // f9
	default:
		LOG_E("[Error] No such Protocol");
	}
}/* }}} */

void MainWidget::processWeightMeasureSocket(const QByteArray &datagram) /*{{{*/
{ 
	//LOG_E("Weight Measure Data");
	const char *udpData = datagram.data();
	assert ( k_protocol_weight_measure == *udpData);
	int packageLength = (*(udpData + 1) + (*(udpData + 2)) * 256);
	int i,j;
	for (i = 0; i < packageLength - 3; i++)
	{
		switch (*(udpData + 3 + i))  
		{
		case NOTICE: 
			{
				QString tmpString; 
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbNotice->setText(tmpString);
				i = i + j + 1;
			}
			break;
		case INFONOTES: 
			{
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbInfonotes->setText(tmpString);
				i = i + j + 1;
			}
			break;
		case TARE: 
			{
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbTare->setText(tmpString);
				i = i + j + 1;
			}
			break;
		case TAREVALUE: 
			{
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbTareValue->setText(tmpString);
				i = i + j + 1; 
			}
			break;
		case WEIGHT: 
			{
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbWeight->setText(tmpString);
				i = i + j + 1;
			}
			break;
		case WEIGHTVALUE: 
			{
				lbWeightWithSymbol->hide();
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbWeightValue->setText(tmpString);
				tbWeightValue->show();
				i = i + j + 1;
			}
			break;
		case PRICE: 
			{
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbPrice->setText(tmpString);
				i = i + j + 1;
			}
			break;
		case PRICEVALUE: 
			{
				lbUnitPriceWithSymbol->hide();
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++)
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbPriceValue->setText(tmpString);
				tbPriceValue->show();
				i = i + j + 1;
			}
			break;
		case TOTALPRICE: 
			{
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbTotalPrice->setText(tmpString);
				i = i + j + 1;
				}
			break;
		case TOTALPRICEVALUE: 
			{
				lbTotalPriceWithSymbol->hide();
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbTotalPriceValue->setText(tmpString);
				tbTotalPriceValue->show();
				i = i + j + 1;
			}
			break;
		case ZERO: 
			{
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				if (charArray[0] == 0x30) {
					m_isUpdateZero = true;
					m_isDisplayZero = false;
				} else {
					m_isUpdateZero = true;
					m_isDisplayZero = true;
				}
				i = i + j + 1;
				if (m_isUpdateZero) {
					m_isUpdateZero = false;
					if (m_isDisplayZero)
						zeroImage->show();
					else
						zeroImage->hide();
				}
			}
			break;
		case MANPREPACK: 
			{
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbManPrepack->setText(tmpString);
				i = i + j + 1;
			}
			break;
		case NETLAMP: 
			{
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbNetLamp->setText(tmpString);
				i = i + j + 1;
			}
			break;
		case MAX: 
			{
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				char firstChar = charArray[0];
				int uFirstChar = int(firstChar);

				if ( "" != QString(charArray)) {
					if (uFirstChar>47 && uFirstChar<58)   //ascii
						m_strMax = QString("Max ") + QString::fromUtf8(charArray) + QString("     ");
					else
						m_strMax = QString::fromUtf8(charArray) + QString("     ");
					m_isMax=true;
				} else {
					m_isMax = false;
				}
				i = i + j + 1;
			}
			break;
		case MIN: 
			{
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);

				char firstChar = charArray[0];
				int uFirstChar = int(firstChar);

				if ( "" != QString(charArray)) {
					if (uFirstChar>47 && uFirstChar<58)   //ascii
						m_strMin = QString("Min ") + QString::fromUtf8(charArray) + QString("     ") ;
					else
						m_strMin = QString::fromUtf8(charArray) + QString("     ") ;
					m_isMin = true;
				} else {
					m_isMin = false;
				}
				i = i + j + 1;
			}
			break;
		case INCREMENT: 
			{
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				char firstChar = charArray[0];
				int uFirstChar = int(firstChar);
				if ( "" != QString(charArray)) {
					if (uFirstChar>47 && uFirstChar<58)   //ascii
						m_strIncrement = QString("e = d = ") + QString::fromUtf8(charArray) + QString("     ");
					else
						m_strIncrement = QString::fromUtf8(charArray) + QString("     ") ;
					m_isIncrement = true;
				}
				else {
					m_isIncrement = false;
				}
				i = i + j + 1;
			}
			break;
		case TARELIMIT: 
			{
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				char firstChar = charArray[0];
				int uFirstChar = int(firstChar);
				if ( "" != QString(charArray)) {
					if ( '-' == firstChar )
						m_strLimit = QString("T = ") + QString::fromUtf8(charArray);  
					else if (uFirstChar>47 && uFirstChar<58)   //ascii
						m_strLimit = QString("T = ") + QString::fromUtf8(charArray); 
					else
						m_strLimit = QString::fromUtf8(charArray); 
					m_isLimit = true;
				} else {
					m_isLimit = false;
				}
				i = i + j + 1;
			}
			break;
		case TARERIGHT: 
			{
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbTareRight->setText(tmpString);
				i = i + j + 1;
			}
			break;
		case WEIGHTRIGHT: 
			{
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbWeightRight->setText(tmpString);
				i = i + j + 1;
			}
			break;
		case PRICERIGHT: 
			{
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbPriceRight->setText(tmpString);
				i = i + j + 1;
			}
			break;
		case TOTALPRICERIGHT: 
			{
				QString tmpString;
				char charArray[*(udpData + 3 + i + 1)];
				for (j = 0; j < *(udpData + 3 + i + 1); j++) 
					charArray[j] = *(udpData + 3 + i + 1 + j + 1);
				tmpString = QString::fromUtf8(charArray);
				tbTotalPriceRight->setText(tmpString);
				i = i + j + 1;
			}
			break;
		default:
			LOG_E("Un-Recognized Protocol");
			break;
		} /* switch */	
	} /* for */

	m_strUnitInfo.clear();
	if (m_isMax) { m_strUnitInfo += m_strMax; }
	if (m_isMin) { m_strUnitInfo += m_strMin; }
	if (m_isIncrement) { m_strUnitInfo += m_strIncrement; }
	if (m_isLimit) { m_strUnitInfo += m_strLimit; } 
	tbMax->setText(m_strUnitInfo);     
}  // End-WeighMeasure
/* }}} */

void MainWidget::processPluSocket(const QByteArray& datagram) /* {{{ */
{ 
	const char *udpData = datagram.data();
	unsigned char charArray[256] = {0};
	for (int i = 0; i < 4; i++) 
		charArray[i] = *(udpData + 2 + i);
	m_pluNo = retrieveInt32(charArray); 
	LOG_E("PLU Socket :%02d", m_pluNo);
	bool needSwitchPartial = false;
	switch(m_layout)
	{
	case k_layout_1:
		{ 
			//this->show(); //Bug#21279, delay showing
			if (EScreenModeOn == m_xbootconf.screenMode()) {
				if (m_screenState == EFullScreen) {
					LOG_E("Do Plu(Full->Partial)");
					m_screenState = EPartialScreen;
					m_event = EPlu;    //for ExitScreenSaver
					needSwitchPartial = true;
				}
			}
			if (0!=m_xlayout1->doPlu(m_pluNo,needSwitchPartial)) {
				LOG_E("[IGNORE][PLU INVALID]");
				if (needSwitchPartial) {
					LOG_E("[Switch to Parital][DoRoutine]");
					m_xlayout1->doRoutine(EPartialScreen);
				}
			}
		}
		return;
	case k_layout_2: case k_layout_4: 	
	case k_layout_6: case k_layout_8:
	case k_layout_9:
		{
			needSwitchPartial = false;
			if (EScreenModeOn == m_xbootconf.screenMode()) {
				if (m_event == EExitScreenSaver) {	
					LOG_E("[SWITCH SCREEN] From ExitScreenMode -> PLU");
					m_event = EPlu;  //pass control from EExitScreenSaver to EPLU
					needSwitchPartial = true;
					if (m_layout != k_layout_6)  //Queue+Video/Html --> XQueueWidget
						this->show();
					else {
						this->hide();
						m_xqueueWidget->show();
					}
				} 
			}
			if (0!=m_xlayoutManager->doPlu(m_pluNo, needSwitchPartial)) {  //Plu is invalid
				if (needSwitchPartial) {
					m_xlayoutManager->doRoutine(needSwitchPartial);
					LOG_E("[INVALID] Temp Plu [Drop]");
				}
			}else {  // PLU Valid
				if (m_layout == k_layout_6) { // Queue + Video/Html
					if (NULL!=m_xqueueWidget) {
						this->hide();  //Gray box
						m_xqueueWidget->stopQueue();
						m_xqueueWidget->show();   //show blue background
					}
				} else if (m_layout == k_layout_8 || m_layout == k_layout_9) {  //WM2+Video/Html
					if (NULL!=m_xqueueWidget) {
						m_xqueueWidget->stopQueue();
						m_xqueueWidget->hide();
					}
				}
			}
		}
		return;
	case k_layout_3: case k_layout_5:  // Html/Video Only
		if (0!=m_xlayoutManager->doPlu(m_pluNo, needSwitchPartial)) {
			LOG_E("[INVALID] Temp Plu [Drop]");
		}
		return;
	default:
		LOG_E("Layout:%02d does not support PLU", m_layout);
		return;
	}
} //End-Plu-Socket
/* }}} */

void MainWidget::processFunctionCommandSocket(const QByteArray & datagram) /* {{{ */
{
	XInfomatFunctionCommand xfunctioncommand;
	XIniFile symbolIniFile;
	if (xfunctioncommand.fromPacket(datagram.data()))  
	{
		uint32_t commandType = xfunctioncommand.getCommandType();
//		LOG_E("command type:%d", commandType);
		std::vector<std::string> parameters;
		parameters = xfunctioncommand.getParameters();
#if 0   //output recieved paramters
		int i=0;
		for (std::vector<std::string>::iterator iter = parameters.begin(); iter != parameters.end(); ++iter, ++i)
			DEBUG("parameter %d: %s", i, (*iter).c_str());
#endif
		if (""==m_currencySymbol) {  /* {{{ */
			if (0!=symbolIniFile.open (Symbol_Ini_File, EIniAddNew)) {
				LOG_E("[Error] open symbol.ini File failed");
			} else {
				char tmpString[32]={0};
				if (0!=symbolIniFile.readString ("",Symbol_Ini_Currency,tmpString,32)) {
					if(0!=symbolIniFile.writeString ("", Symbol_Ini_Currency,""))
						LOG_E("[Error] Write Currency Symbol into symbol.ini File");
				} else {
					m_currencySymbol = QString(tmpString);
				}
				if (""==m_currencySymbol)
					m_currencySymbol="$";   //default value
				symbolIniFile.flush();
				symbolIniFile.close();
			}
		}
		if (""==m_currencySymbolPos) {
			if (0!=symbolIniFile.open (Symbol_Ini_File, EIniAddNew)) {
				LOG_E("[ERROR] Open symbol.ini failed");
			} else {
				int tmpInt;
				if (0!=symbolIniFile.readInt ("",Symbol_Ini_Position,tmpInt)) {
					if(0!=symbolIniFile.writeString ("", Symbol_Ini_Position,""))
							LOG_E("[Error] Write Currency Symbol Position into symbol.ini File");
				} else {
					m_currencySymbolPos = QString::number(tmpInt);
				}
			}
			symbolIniFile.flush();
			symbolIniFile.close();
		}

		if (""==m_quantityUnitPriceSeparator) {
			if (0!=symbolIniFile.open (Symbol_Ini_File, EIniAddNew))
				LOG_E("[Error] open symbol.ini File");
			else {
				char tmpString[32] = {0};
				if (0!=symbolIniFile.readString ("",Symbol_Ini_Separator,tmpString,32)) {	
					if(0!=symbolIniFile.writeString ("", Symbol_Ini_Separator,""))
						LOG_E("[Error] Write Currency Symbol into symbol.ini File");
				} else {
					m_quantityUnitPriceSeparator = QString(tmpString);
				}
				symbolIniFile.flush();
				symbolIniFile.close();
			}
		}
		// Symbol Text
		if (m_layout == k_layout_1 || m_layout == k_layout_2 ||
			m_layout == k_layout_4 || m_layout == k_layout_8 ||
			m_layout == k_layout_9 || m_layout == k_layout_10) 
		{
			switch (commandType)
			{
			case EInfomatDisplayFunction_displayQuantityWithSymbol:  //for WM only
				{   
					tbWeightValue->hide();
					QString textBeforeSymbol, firstSymbol, textAfterSymbol, secondSymbol;
					textAfterSymbol = QString::fromUtf8(parameters[0].c_str());
					secondSymbol = QString::fromUtf8 (parameters[1].c_str());
					lbWeightWithSymbol->setText(textBeforeSymbol, firstSymbol, textAfterSymbol, secondSymbol);
					lbWeightWithSymbol->show();
					return;
				}
			case EInfomatDisplayFunction_displayTotalPriceWithSymbol:
				{
					tbTotalPriceValue->hide();
					QString textBeforeSymbol, firstSymbol, textAfterSymbol, secondSymbol;
					firstSymbol = m_currencySymbol;
					textAfterSymbol = QString::fromUtf8 (parameters[0].c_str());
					lbTotalPriceWithSymbol->setText(textBeforeSymbol, firstSymbol, textAfterSymbol, secondSymbol);
					lbTotalPriceWithSymbol->show();
					return;
				}
			case EInfomatDisplayFunction_displayUnitPriceWithSymbol_1:   //Sample: $999.99/pc
				{
					QString textBeforeSymbol, firstSymbol, textAfterSymbol, secondSymbol;
					tbPriceValue->hide();
					if ( "0" == m_currencySymbolPos) {
					textAfterSymbol = QString::fromUtf8 (parameters[0].c_str());
					firstSymbol = m_currencySymbol; 
					} else {
						secondSymbol = m_currencySymbol;
						textAfterSymbol = QString::fromUtf8 (parameters[0].c_str());
					}
					QString perUnitSymbol = QString::fromUtf8 (parameters[1].c_str());

					secondSymbol = m_quantityUnitPriceSeparator + perUnitSymbol;
					lbUnitPriceWithSymbol->setText(textBeforeSymbol, firstSymbol, textAfterSymbol, secondSymbol);
					lbUnitPriceWithSymbol->show();
					return;
				}
			case EInfomatDisplayFunction_displayUnitPriceWithSymbol_2:   //Sample:999oz/$999.99
				{
					tbPriceValue->hide();
					QString textBeforeSymbol, firstSymbol, textAfterSymbol, secondSymbol;
					QString quantity = QString::fromUtf8(parameters[0].c_str());
					textBeforeSymbol = quantity;
					firstSymbol =  QString::fromUtf8(parameters[1].c_str()) + m_quantityUnitPriceSeparator + m_currencySymbol;
					textAfterSymbol = QString::fromUtf8(parameters[2].c_str());
					lbUnitPriceWithSymbol->setText(textBeforeSymbol, firstSymbol, textAfterSymbol, secondSymbol);
					lbUnitPriceWithSymbol->show();
					return;
				}
			case EInfomatDisplayFunction_setCurrencySymbol:
				{
					QString currencySymbol = QString::fromUtf8(parameters[0].c_str());
					if (""!=currencySymbol) {
						m_currencySymbol = currencySymbol;
						if (0!=symbolIniFile.open (Symbol_Ini_File, EIniReadWrite))
							LOG_E("[Error] Open symbol.ini File");
						else {
							if(0!=symbolIniFile.writeString ("", Symbol_Ini_Currency,currencySymbol.toStdString().c_str()))
								LOG_E("[Error] Write Currency Symbol into symbol.ini File");
							symbolIniFile.flush();
							symbolIniFile.close();
						}
					}
					return;
				}
			case EInfomatDisplayFunction_setCurrencySymbolPosition:
				{
					QString currencySymbolPosition = QString::fromUtf8(parameters[0].c_str());
					if (""!=currencySymbolPosition) {
						m_currencySymbolPos = currencySymbolPosition;
						if (0!=symbolIniFile.open (Symbol_Ini_File,EIniReadWrite))
							LOG_E("[Error] Open symbol.ini File");
						else {
							if(0!=symbolIniFile.writeString ("", Symbol_Ini_Position,currencySymbolPosition.toStdString().c_str()))
								LOG_E("[Error] Write Currency Symbol Position into symbol.ini File");
							symbolIniFile.flush();
							symbolIniFile.close();
						}
					}
					return;
				}
			case EInfomatDisplayFunction_setQuantityUnitPriceSeparator:
				{
					QString separator = QString::fromUtf8(parameters[0].c_str());
					if (""!=separator) {
						m_quantityUnitPriceSeparator = separator;
						if (0!=symbolIniFile.open (Symbol_Ini_File, EIniReadWrite))
							LOG_E("[Error] Open symbol.ini File");
						else {
							if(0!=symbolIniFile.writeString ("", Symbol_Ini_Separator,separator.toStdString().c_str()))
								LOG_E("[Error] Write Currency Symbol into symbol.ini File");
							symbolIniFile.flush();
							symbolIniFile.close();
						}
					}
					return;
				}
			}
		} /* }}} */
		// Screen Switch Command
		switch (commandType) 
		{
		case EInfomatDisplayFunction_enterScreenSaver:
			{  /* {{{ */
				LOG_E("[Protocol] enterScreenSaver");
				if (EScreenModeOff == m_xbootconf.screenMode()) {
					LOG_E("Return, ScreenMode [OFF] (boot.conf)");
					return;
				}
				if (m_event != EEnterScreenSaver) {
					m_event = EEnterScreenSaver;
				} else {
					LOG_E("[Repeat][EnterScreenSaver][Return]");
					return;
				}
				if (m_layout == k_layout_3 || m_layout==k_layout_5) { LOG_E("Return, VIDEO/HTML Not Support"); return; }
				else if (m_layout == k_layout_7 ) { LOG_E("Return, Queue Not Support"); return; }
				else if (m_layout == k_layout_10) { LOG_E ("Return, Queue+WM2 Not Support"); return; }
				else this->hide(); 
				m_screenState = EFullScreen;
				//Process Queue if has
				if ( m_xqueueWidget != NULL) {
					if (m_layout == k_layout_6) {
						LOG_E("Hide Queue");
						this->hide();   //gray box: XQueueWidget control UI
						m_xqueueWidget->stopQueue();
						m_xqueueWidget->hide();
					}
				}
				if (NULL!=m_xlayoutManager)  m_xlayoutManager->doEnterScreenSaver();
				else if (NULL!=m_xlayout1)  m_xlayout1->doEnterScreenSaver();
				return;
			} /* }}} */
		case EInfomatDisplayFunction_enterMenuMode:  //enter menu mode,full screen
			{  /* {{{ */
				if (EScreenModeOff == m_xbootconf.screenMode()) {
					LOG_E("Return, ScreebMode [OFF] (boot.conf)");
					return;
				}
				LOG_E("[Protocol]: enterMenuMode");
				if (m_event == EExitScreenSaver) {
					m_event = EEnterMenuMode;
					LOG_E("[From ExitScreenSaver To  EnterMenuMode] [Do Nothing]");
					return;
				}
				if (m_event != EEnterMenuMode) {
					m_event = EEnterMenuMode;
				} else {
					LOG_E("[Repeated Command][EnterMenuMode][Return]");
					return;
				}

				switch (m_layout) //hide WM
				{
				case k_layout_1: case k_layout_2: case k_layout_4: 
					this->hide(); //WM1
					break;
				case k_layout_3: case k_layout_5:
					LOG_E("[Fatal Error] VIDEO/HTML Not Support"); 
					return;
				case k_layout_6:  //Queue + Video/Html  (logo+SmallQueue)
					this->hide();   //gray box: XQueueWidget control UI
					if (NULL!=m_xqueueWidget) {
						m_xqueueWidget->stopQueue();
						m_xqueueWidget->hide();
					}
					break;
				case k_layout_7:
					LOG_E("Queue Only Not Support"); 
					return;
				case k_layout_8: case k_layout_9:
					this->hide();   //Hide WM
					if (NULL!=m_xqueueWidget) {
						m_xqueueWidget->stopQueue();
						m_xqueueWidget->hide();
					}
					break;
				case k_layout_10:  // resume queue
					assert(NULL!=m_xqueueWidget);
					m_xqueueWidget->show();
					return;
				}

				m_screenState = EFullScreen;
				if (m_xlayoutManager!=NULL) {
					m_xlayoutManager->doEnterMenuMode();
				} else {
					if (m_xlayout1!=NULL) {
						m_xlayout1->doEnterMenuMode();
					}
				}
				return;
			}  /* }}}*/
		case EInfomatDisplayFunction_exitScreenSaver:
			{ /* {{{ */
				if (EScreenModeOff == m_xbootconf.screenMode()) {
					LOG_E("[Return] [exitScreenSaver][EScreenModeOff]");
					return;
				}
				LOG_E("[Protocol] : exitScreenSaver");
				if (m_event != EExitScreenSaver) {
					m_event = EExitScreenSaver;
				} else {
					LOG_E("[Repeat][exitScreenSaver][Return]");
					return;
				}
				if (m_layout == k_layout_3 || m_layout == k_layout_5 ) { LOG_E("[Return] [Video][Html] [NotSupport]"); return;}
				else if (m_layout == k_layout_7 ) { LOG_E("[Return] [Queue Only] [NotSupport]"); return;}
				else if (m_layout == k_layout_6 ) { 
					this->hide();
					if (m_xqueueWidget != NULL) {
						m_xqueueWidget->hide();
					}
				}
				else if (m_layout == k_layout_10) { 
					this->show();
					m_xqueueWidget->show();
					LOG_E("Return, Queue+WM2 Not Support"); 
					return;
				}
				m_tmCmdCtrl.start(500);   //do commands sequence check
				return;
			} /*  }}} */
		case EInfomatDisplayFunction_exitMenuMode:   // SM5500 exit menu mode, Infomat does partial screen showing
			{ /*  {{{  */
				LOG_E("[Protocol] exitMenuMode");
				if (EScreenModeOff == m_xbootconf.screenMode()) { LOG_E("Return, ScreenMode [Off] (boot.conf)"); return;} 
				if (m_event != EExitMenuMode) {
					m_event = EExitMenuMode;
				} else {
					LOG_E("[Repeat][exitMenuMode][Return]");
					return;
				}
				
				if (m_layout == k_layout_3 || m_layout == k_layout_5 ) { LOG_E("Return, VIDEO/HTML Not Support"); return;}
				else if (m_layout == k_layout_7) {LOG_E("Return, Queue Only"); return;}
				else if (k_layout_10==m_layout) { LOG_E("return, WM2+Queue No Support"); return; }
				else if (m_layout == k_layout_6) {
					this->hide();
					if (NULL!=m_xqueueWidget) {
						m_xqueueWidget->hide();
					}
				}
				else
					this->show();

				m_screenState = EPartialScreen;  //Plu

				if (m_xlayoutManager!=NULL) {
					m_xlayoutManager->doExitMenuMode();
				 	if (m_layout == k_layout_6) {
						this->hide();
						if (NULL!=m_xqueueWidget) {
							LOG_E("Show Queue");
							if (m_hasSentQueue) {
								m_xqueueWidget->keepSmallQueue(); //new queue
								m_xqueueWidget->show();
							}else{
								m_xqueueWidget->resumeWidget();   //after resume no logo 
							}
						}
					}

				} else {
					if (NULL!= m_xlayout1) 
					m_xlayout1->doExitMenuMode();
				}
				return;
			} /* }}} */
		case EInfomatDisplayFunction_start:   //Resume From Halt Stat
			{ /* {{{ */
				LOG_E("<SM5500 starts, Infomat resumes from Halt State>");
				tws_system("/opt/S99start &");
				if(m_lblPowerOff==NULL)  {
					break;
				} else {
					delete m_lblPowerOff;           // destory the infomation
				    m_lblPowerOff = NULL;
				}

				if (m_xlayoutManager !=NULL) {
					m_xlayoutManager->doResume();  // full/partial
				} else if (m_xlayout1 != NULL) {
						m_xlayout1->doResume();
				} 
				
				if (NULL!=m_xqueueWidget) {   //Queue do reusme
					m_xqueueWidget->doResume();
				}

				if (EScreenModeOn == m_xbootconf.screenMode()) {   //Full screen
					this->hide();
					if (m_layout == k_layout_10) {
						this->show();  //WM2 + Queue
					}
				} else {  // partial screen
					switch (m_layout) 
					{
					case k_layout_10:   //wm2
					case k_layout_9:
					case k_layout_8:
					case k_layout_1:    //wm1
					case k_layout_2:
					case k_layout_4:
						this->show();
						break;
					case k_layout_7:   //Queue
					case k_layout_6:   //Queue + Video/Media
					case k_layout_3:
					case k_layout_5:
						this->hide();
						break;
					}
				}

				return; 
			}
		default:
			return;
		} /* }}} */
	}
}/* }}} */

void MainWidget::processQueueSocket(const QByteArray& datagram)  /* {{{ */
{ 
	unsigned char charArray[256] = { 0 };
	for (int i = 0; i < 4; i++)
		charArray[i] = *(datagram.data() + 2 + i);
	int queueNumber = retrieveInt32(charArray);
//	LOG_E("[Queue]Queue Number: %d", queueNumber);
	/* if the layout has players */
	LOG_E("event : m_event");
	m_event = EQueue;
	if (m_layout==k_layout_8 || m_layout==k_layout_9 || m_layout==k_layout_10) {
//		LOG_E("Porcess Queue : WM2");
		this->show();
		lbDigiLogo->hide();
		m_lbqno->setText(QString::number(queueNumber));
		m_lbqno->show();
		m_lbqno->raise();
		this->repaint();
	}
	if (NULL!=m_xlayoutManager) {
//		LOG_E("Request XLayoutmanager to Stop Player");
		m_xlayoutManager->doQueue();
	}
	LOG_E("Show Queue");
	m_xqueueWidget->showQueue(queueNumber);
	m_hasSentQueue = true;
} /* }}} */

void MainWidget::processCommandSocket(const QByteArray &datagram) /* {{{ */
{
	const char *udpData = datagram.data();
	char cmd = *(udpData + 2);
	if (cmd == 'b') {
		LOG_E("Process Command Sokcet: backlight");
		lighton = *(udpData + 3);   //'b': backlight control
	}
	if (cmd == 'v') {
		LOG_E("Process Command: Volume");
		volumeData = *(udpData + 3);//'v': volume value
	}
	readCmd(cmd);
	if ((cmd == 'v') || (cmd == 'b')) {
		LOG_E("Process Command: v or b");
		processCmd();
	}
}/* }}} */

void MainWidget::processCmd() /* {{{ */
{
	if (cmdMode & CMD_VOLUME) 
	{
		if (volumeData > 125)
			volumeData = 115;
		char buf0[64];
		sprintf(buf0, "amixer sset Master %d", volumeData);
		tws_system(buf0);
		sprintf(buf0, "/opt/S99volume %d", volumeData);
		tws_system(buf0);
		cmdMode &= ~CMD_VOLUME;
	}
	if (cmdMode & CMD_VERSION) 
	{
		LOG_E("Read Version Command");
		readVersion();
		cmdMode &= ~CMD_VERSION;
	}
	if (cmdMode & CMD_BACKLIGHT) {
		if (lighton)
			tws_system("/opt/S99lighton");
		else
			tws_system("/opt/S99lightoff");
		cmdMode &= ~CMD_BACKLIGHT;
	}
	if (cmdMode & CMD_INIT) {
		LOG_E("Run initialize script: S99init");
		cmdProc->start("/opt/S99init");
		cmdMode &= ~CMD_INIT;
		return;
	}
	if (cmdMode & CMD_DEFAULT) {
		LOG_E("Run default script S99restore");
		tws_system("/opt/S99restore &");
		cmdMode &= ~CMD_DEFAULT;
		qApp->quit();
		return;
	}
	if (cmdMode & CMD_UPDATE) {
		DEBUG("processCmd: 'u', exit run /opt/S99update");
		tws_system("/opt/S99update &");
		cmdMode &= ~CMD_UPDATE;
		qApp->quit();
		return;
	}
	if (cmdMode & CMD_REBOOT) {
		DEBUG("processCmd: 'r', exit & run /opt/S99reboot");
		tws_system("/opt/S99reboot &");
		cmdMode &= ~CMD_REBOOT;
		qApp->quit();
	}
	if (cmdMode & CMD_HALT) {
		LOG_E("Receive Halt Command:");
		if (NULL!=m_xlayoutManager) {
			m_xlayoutManager->doHalt();
		} else {
			if (NULL!=m_xlayout1) {
				m_xlayout1->doHalt();
			}
		}
	
		if (m_xqueueWidget!=NULL) {
			m_hasSentQueue = false;

			//WeightMeasuer2
			if (m_layout == k_layout_8 || m_layout == k_layout_9 || m_layout == k_layout_10) {
				m_lbqno->hide();
				lbDigiLogo->show();  
				this->hide();
			}
			m_xqueueWidget->doHalt();
		}
		
		LOG_E("Generate Power Off label");
		m_lblPowerOff = new QLabel();
		m_lblPowerOff->setGeometry(0,0,800,600);
		QPixmap bgPicture = QPixmap(QString(k_bg_poweroff));
		m_lblPowerOff->setPixmap(bgPicture);
		m_lblPowerOff->show();
		LOG_E("Showing Power Off Infomation, call S99halt");
		tws_system("/opt/S99halt &");
		LOG_E("Halt Command Process Over");
//      New Halt. End <<
		return;
	}
	if (cmdMode == 0)
		return;
}/* }}} */

void MainWidget::onFromExitScreenSaver()  /* {{{ */
{
	m_tmCmdCtrl.stop();
//	LOG_E("onFromExitScreenSaver Checking");
//	LOG_E("Current Event: %02d", m_event);
	if (m_event == EExitScreenSaver) {
		LOG_E("[Confirm][FromExitScreenMode] EExitScreenMode");
		this->show();
		if (m_layout == k_layout_6) {
			this->hide();
			//m_xqueueWidget->show();   //todo:verify, delay show in QueueWidgetRepaint
		}  
		if (m_layout == k_layout_8 || m_layout == k_layout_9) {
			this->show();
			m_xqueueWidget->show();
		}
		m_screenState = EPartialScreen;
		if (m_xlayoutManager!=NULL) {
			m_xlayoutManager->doExitScreenSaver();
		}else if (m_xlayout1!=NULL) {
			m_xlayout1->doExitScreenSaver();
		}
		m_event = ENoEvent;
			return;
	}
//	LOG_E("[IGNORE] onFromExitScreenSaver");
}/* }}} */

void MainWidget::onWMRepaint()  /* {{{ */
{
	LOG_E("[Slot] Repaint Weigh Measure");
	if (m_layout == k_layout_1) {
		this->show();
		this->repaint();
	}

	if(m_layout == k_layout_8 || m_layout == k_layout_9 || m_layout == k_layout_10) {
		this->repaint();
	}
}/* }}} */

void MainWidget::onQueueWidgetRepaint()  /* {{{ */
{
	if (m_layout == k_layout_6) {
		LOG_E("Hide Queue Widget");
		m_xqueueWidget->hide();
		LOG_E("[Slot] Repaint Queue Repaint");
		if (NULL!=m_xqueueWidget) {
			if (m_hasSentQueue) {
				LOG_E("Show Queue Widget: keep small queue");
				m_xqueueWidget->keepSmallQueue(); //new queue
			}else{
				LOG_E("Show Queue : resumeWidget");
				m_xqueueWidget->resumeWidget();   //after resume no logo 
			}
			m_xqueueWidget->show();
	//		m_xqueueWidget->repaint();
		}
	}
}/* }}} */

/* ******  copy original code ********* */
int MainWidget::parseValue(QString _buffer)  /* {{{ */
{ 
	QString dummy1;
	int ret = 0;
	dummy1 = _buffer.section('=', 1, 1);
	if (dummy1.trimmed().compare("") != 0) {
		bool ok;
		int dec = dummy1.trimmed().toInt(&ok, 10);
		if (ok)
			ret = dec;
	}
	return ret;
}/*}}} */

void MainWidget::readCmd(char cmd)  /* {{{ */
{
	cmdPending = true;
	switch (cmd) 
	{
	case 'i':
		cmdMode |= CMD_INIT;
		break;
	case 'r':
		cmdMode |= CMD_REBOOT;
		break;
	case 'd':
		cmdMode |= CMD_DEFAULT;
		break;
	case 'u':
		cmdMode |= CMD_UPDATE;
		break;
	case 'h':
		cmdMode |= CMD_HALT;
		break;
	case 'V':
		cmdMode |= CMD_VERSION;
		break;
	case 'v':
		cmdMode |= CMD_VOLUME;
		break;
	case 'b':
		cmdMode |= CMD_BACKLIGHT;
		break;

	default:
		cmdPending = false;
		LOG_E("processCmd: unknown command");
		break;
	}
	if (cmdMode | (CMD_REBOOT | CMD_DEFAULT | CMD_UPDATE | CMD_HALT
				   | CMD_VERSION))
		processCmd();
}/* }}} */

void MainWidget::readVersion()  /* {{{ */
{	
	QFile ConfigFile;
	int _major = 0, _minor = 0, _release = 0, _build = 0;
	ConfigFile.setFileName("/usr/infomat/VERSION");
	QTextStream stream(&ConfigFile);
	if (ConfigFile.open(QIODevice::ReadOnly)) {
		while (!stream.atEnd()) {
			QString buffer;
			QString dummy;
			buffer = stream.readLine();
			dummy = buffer.section('=', 0, 0);
			if (dummy.trimmed().compare("MAJOR") == 0) {
				_major = parseValue(buffer);
			} else if (dummy.trimmed().compare("MINOR") == 0) {
				_minor = parseValue(buffer);
			} else if (dummy.trimmed().compare("RELEASE") == 0) {
				_release = parseValue(buffer);
			} else if (dummy.trimmed().compare("BUILD") == 0) {
				_build = parseValue(buffer);
			}
		}
	}
	ConfigFile.close();
	QByteArray datagram = "V" + QByteArray::number(_major) + "."
		+ QByteArray::number(_minor) + "." + QByteArray::number(_release)
		+ "-" + QByteArray::number(_build);
	LOG_E("readVersion");
	udpSocketOut->writeDatagram(datagram.data(), datagram.size(),QHostAddress::Broadcast, udpPort + 1);
}	/* }}} */
/* *****   End Copy ****************** */
